/* Team 5
 * James McQueen
 * Corwyn Simpson
 * May 1 ish, 2012
 */
package spider.stores;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import spider.models.Data;

/**
 * Description for a DataGatherer
 *      A DataGatherer contains a set of results obtained from
 *      crawling the web.
 * @author James McQueen
 * @author Corwyn Simpson
 */
public class DataGatherer 
{
    /**
     * The "raw" data, where the individual data entries are stored.
     */
    private Set<Data> my_individual_results;
    /**
     * An accumulation of the data entries, where the keyword is the key and the
     * number of appearances is the value attached to each key.
     */
    private Map<String, Integer> my_cumulative_results;
    
    /**
     * Creates a new, blank DataGatherer.
     */
    public DataGatherer()
    {
        my_individual_results = new HashSet<Data>();
        my_cumulative_results = new HashMap<String, Integer>();
    }
    
    /**
     * Checks to see if the_data is already in this DataGatherer
     * @param the_data The keyword to check for
     * @return True if the_data is already stored in this DataGatherer
     */
    public boolean containsResult(final Data the_data)
    {
        return(my_individual_results.contains(the_data));
    }
    
    /**
     * Adds a collection of Data to this DataGatherer, storing both running 
     * totals as well as individual entries.
     * @param the_collection The collection of Data to add to this DataGatherer
     * @return True if at least one element in the_collection was not already in
     * this DataGatherer.
     */
    public synchronized boolean addAllResults(Collection<? extends Data> the_collection)
    {
        for (Data data : the_collection)
        {
            int count = data.getMatches();
            if (my_cumulative_results.containsKey(data.getData()))
                count += my_cumulative_results.get(data.getData());
            my_cumulative_results.put(data.getData(), count);
        }
        return my_individual_results.addAll(the_collection);
    }
        
    /**
     * Clears this DataGatherer, reseting all recorded data.
     */
    public void clearResults()
    {
        my_individual_results.clear();
        my_cumulative_results.clear();
    }
    
    /**
     * Returns the total number of entries recorded by this DataGatherer
     */
    public int getResultCount()
    {
        return my_individual_results.size();
    }
    
    /**
     * Returns the number of unique sources (URLs) that the data came from.
     * This will only be consistent if each URL had the same number of keywords.
     */
    public int getSourceCount()
    {
        int result = 0;
        if (my_cumulative_results.size() > 0)
        {
            result = my_individual_results.size() / my_cumulative_results.size();
        }
        return result;
    }
    
    /**
     * Returns a print-friendly string representing the cumulative results of 
     * the web crawler, formatted as per the project specifications.
     */
    public String getResultsString()
    {
        StringBuilder result = new StringBuilder();
        result.append("Cumulative results\n");
        for (Map.Entry<String, Integer> entry : my_cumulative_results.entrySet())
        {
            result.append(String.format("%s\t%d\n", entry.getKey(), entry.getValue()));
        }
        return result.toString();
    }
    
    /**
     * Returns an immutable set wrapping for the cumulative results from the 
     * gathered data.
     */
    public Map<String, Integer> getCumulativeResults()
    {
        return Collections.unmodifiableMap(my_cumulative_results);
    }
    
    /**
     * Returns an immutable set wrapping for the individual page results from 
     * the gathered data.
     */
    public Set<Data> getIndividualResults()
    {
        return Collections.unmodifiableSet(my_individual_results);
    }

    @Override
    public String toString() 
    {
        return "DataGatherer{" + "my_results_set=" + my_individual_results + '}';
    }
}